package com.checkchan.ethshare.contract;

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.*;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.utils.Convert;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;

public class ShareContract extends Contract implements ShareInterface {

    //编译后的智能合约
    private static final String BINARY = "608060405234801561001057600080fd5b5061079a806100206000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631795e99b1461007a5780631c0b915b146100ff5780631d92d3b91461012a5780632fd9193414610211578063d75b653f1461027a578063f07ad7241461029a575b005b34801561008657600080fd5b506100af60048036038101908080359060200190929190803590602001909291905050506102db565b604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390f35b34801561010b57600080fd5b50610114610351565b6040518082815260200191505060405180910390f35b34801561013657600080fd5b506101556004803603810190808035906020019092919050505061035d565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001848152602001838152602001828103825285818151815260200191508051906020019080838360005b838110156101d35780820151818401526020810190506101b8565b50505050905090810190601f1680156102005780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561021d57600080fd5b50610278600480360381019080803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610463565b005b61029860048036038101908080359060200190929190505050610548565b005b3480156102a657600080fd5b506102c5600480360381019080803590602001909291905050506106a0565b6040518082815260200191505060405180910390f35b6000806000806000868154811015156102f057fe5b9060005260206000209060050201600401600086815260200190815260200160002090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681600101548260020154935093509350509250925092565b60008080549050905090565b600060606000806000808681548110151561037457fe5b906000526020600020906005020190508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160010182600201548360030154828054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505092509450945094509450509193509193565b60006080604051908101604052803373ffffffffffffffffffffffffffffffffffffffff1681526020018381526020016000815260200160008152509080600181540180825580915050906001820390600052602060002090600502016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101908051906020019061052d9291906106c9565b50604082015181600201556060820151816003015550505050565b6000808281548110151561055857fe5b906000526020600020906005020190508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156105d2573d6000803e3d6000fd5b503481600201600082825401925050819055506060604051908101604052803373ffffffffffffffffffffffffffffffffffffffff1681526020013481526020014281525081600401600083600301600081548092919060010191905055815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201559050505050565b600080828154811015156106b057fe5b9060005260206000209060050201600301549050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061070a57805160ff1916838001178555610738565b82800160010185558215610738579182015b8281111561073757825182559160200191906001019061071c565b5b5090506107459190610749565b5090565b61076b91905b8082111561076757600081600090555060010161074f565b5090565b905600a165627a7a72305820f6c515e99e078303779996084bdf0731fcfa2643894c0a63901fe1f7456d9d1f0029";

    protected ShareContract(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
    }


    /**
     * 部署智能合约
     *
     * @param web3j
     * @param credentials
     * @param gasPrice
     * @param gasLimit
     * @return
     */
    public static RemoteCall<ShareContract> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        String encodeConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList());

        return deployRemoteCall(ShareContract.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodeConstructor);
    }

    /**
     * 部署完智能合约后，加载智能合约，如果已经部署，就可以直接加载
     *
     * @param contractAddress
     * @param web3j
     * @param credentials
     * @param gasPrice
     * @param gasLimit
     * @return
     */
    public static ShareContract load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return new ShareContract(contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    @Override
    public RemoteCall<Uint256> getShareCount() {
        Function function = new Function("getShareCount", Arrays.<Type>asList(), Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {
        }));

        return executeRemoteCallSingleValueReturn(function);
    }

    @Override
    public RemoteCall<List<Type>> getShareInfo(int shareIndex) {
        Function function = new Function("getShareInfo"
                , Arrays.<Type>asList(new Uint256(shareIndex))
                , Arrays.<TypeReference<?>>asList(
                new TypeReference<Address>() {
                }
                , new TypeReference<Utf8String>() {
                }
                , new TypeReference<Uint256>() {
                }
                , new TypeReference<Uint256>() {
                }));

        return executeRemoteCallMultipleValueReturn(function);
    }

    @Override
    public RemoteCall<Uint256> getConfereeCount(int shareIndex) {
        Function function = new Function("getConfereeCount"
                , Arrays.<Type>asList(new Uint256(shareIndex))
                , Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() { }));
        return executeRemoteCallSingleValueReturn(function);
    }

    @Override
    public RemoteCall<List<Type>> getConfereeInfo(int shareIndex, int confereeIndex) {
        Function function = new Function("getConfereeInfo"
                ,Arrays.<Type>asList(new Uint256(shareIndex),new Uint256(confereeIndex))
                ,Arrays.<TypeReference<?>>asList(
                new TypeReference<Address>() {
                }
                , new TypeReference<Uint256>() {
                }
                , new TypeReference<Uint256>() {
                }));

        return executeRemoteCallMultipleValueReturn(function);
    }

    @Override
    public RemoteCall<TransactionReceipt> raiseShare(String desc) {
        Function function = new Function("raiseShare",Arrays.<Type>asList(new Utf8String(desc)),Arrays.<TypeReference<?>>asList());

        return executeRemoteCallTransaction(function);
    }

    @Override
    public RemoteCall<TransactionReceipt> gradeShare(int index, int score) {
        Function function = new Function("gradeShare",Arrays.<Type>asList(new Uint256(index)),Arrays.<TypeReference<?>>asList());

        return executeRemoteCallTransaction(function,BigInteger.valueOf(score).multiply(Convert.Unit.ETHER.getWeiFactor().toBigInteger()));
    }
}
